<?php declare(strict_types=1);

namespace App\Api\V2\Controller\Embed;

use App\Api\Controllers\BaseController;
use App\Api\Controllers\Config\LeshuaUnionPayConfigController;
use App\Api\Controllers\LeshuaUnion\LogicController;
use App\Api\Controllers\Merchant\PayBaseController;
use App\Exceptions\BizException;
use App\Models\Merchant;
use App\Models\Store;
use App\Models\StorePayWay;
use App\Models\UserRate;
use App\Services\Pay\ResultVo;
use App\Traits\ResponseTrait;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\Rule;

class EmbedController extends BaseController
{
    use ResponseTrait;

    protected $embedPay = ["leshuaunion"];

    protected $appId = "wx38a3350891b22014";

    public function embedPay(Request $request): string
    {
        try {
            $data = $request->all();
            $validator = Validator::make($data, [
                "store_id" => "required",
                "total_amount" => ["required", "min:0", "numeric"],
                "merchant_id" => ["required"],
                "notify_url" => ["nullable"],
                "timestamp" => ["required"],
                "sign" => ["required"]
            ]);
            if ($validator->fails()) {
                throw new BizException($validator->errors()->first());
            }
            $sign = $data["sign"];
            unset($data["sign"]);
            $string = $this->getSignContent($data) . '&key=' . "88888888";
            Log::channel("embedPay")->info("embedPay", [
                "string" => $string,
                "req" => $data
            ]);
            $string = md5($string);
            if ($sign != $string) {
                throw new BizException("签名校验失败");
            }
            $store = Store::query()->where("store_id", $data["store_id"])->first();
            if (empty($store)) {
                throw new BizException("门店不存在");
            }
            //关闭的商户禁止交易
            if ($store->is_close || $store->is_admin_close || $store->is_delete || $store->state == 3) {
                throw  new BizException("商户已经关闭");
            }
            if ($store->status != 1) {
                throw  new BizException("商户已经关闭");
            }
            $ways = $this->getWaysPay((string)$store->store_id, (int)$store->pid);
            if (!in_array($ways->company, $this->embedPay)) {
                throw new BizException("当前设置的支付方式，不支持半屏支付，请到后台重新设置");
            }
            list($isRun, $error) = \App\Services\Store\StoreSignService::validateSign((string)$store->store_id, (string)$ways->company);
            if ($isRun == false) {
                throw new BizException($error);
            }

            $merchant = Merchant::query()->find($data["merchant_id"]);
            if (empty($merchant)) {
                throw new BizException("收银员不存在");
            }
            //预下单
            $data = $this->prePay($store, $ways, $merchant, $data);
            return $this->successResponse("ok", ["data" => $data]);
        } catch (\Throwable $e) {
            return $this->errorResponse($e->getMessage());
        }
    }

    protected function prePay(Store $store, StorePayWay $ways, Merchant $merchant, array $data): array
    {
        $out_trade_no = date('YmdHis', time()) . substr(microtime(), 2, 6) . sprintf('%03d', rand(0, 999));
        switch ($ways->company) {
            case "leshuaunion":
                $resultVo = $this->leshua($store, $ways, [
                    "out_trade_no" => $out_trade_no,
                    "total_amount" => $data["total_amount"],
                    "store_id" => $store->store_id,
                    "merchant_id" => $merchant->id,
                    "notify_url" => $data["notify_url"] ?? ""
                ]);
                $other_no = $resultVo->getData()["pre_order"] ?? "";
                $mchNo = $resultVo->getData()["CUST_ID"] ?? "";;
                $path = "pages/plugin/pay?preOrderId=" . $other_no . "&merchantId=" . $mchNo;
                break;
            default:
                throw new BizException("不支持的半屏支持");
        }
        if ($resultVo->getCode() != 1) {
            throw new BizException($resultVo->getMsg());
        }
        //插入数据库
        $data_insert = [
            'trade_no' => '',
            'user_id' => $store->user_id,
            'store_id' => $store->store_id,
            'store_name' => $store->store_name,
            'buyer_id' => '',
            'total_amount' => $data["total_amount"],
            'shop_price' => $data["total_amount"],
            'payment_method' => '',
            'status' => '',
            'pay_status' => 2,
            'pay_status_desc' => '等待支付',
            'merchant_id' => empty($merchant) ? 0 : $merchant->id,
            'merchant_name' => empty($merchant) ? "" : $merchant->name,
            'remark' => "",
            'device_id' => "embed",
            'config_id' => "1234",
            'pay_method' => "embedPay",
            "notify_url" => $data["notify_url"] ?? ""
        ];
        $user_rate_obj = $this->getCostRate($ways->ways_type, $store->user_id);
        $cost_rate = $user_rate_obj ? $user_rate_obj->rate : 0.00; //成本费率
        //扫码费率入库
        if ($cost_rate) $data_insert['cost_rate'] = $cost_rate;
        $data_insert['rate'] = $ways->rate;
        $data_insert['fee_amount'] = $ways->rate * $data["total_amount"] / 100;
        $ways_source_desc = "";
        switch ($ways->ways_source) {
            case "weixin":
                $ways_source_desc = "微信支付";
                break;
            case "alipay":
                $ways_source_desc = "支付宝";
                break;
            case "unionpay":
                $ways_source_desc = "云闪付";
                break;
        }
        //入库参数
        $data_insert['out_trade_no'] = $out_trade_no;
        $data_insert['ways_type'] = $ways->ways_type;
        $data_insert['ways_type_desc'] = $ways->ways_desc;
        $data_insert['ways_source'] = $ways->ways_source;
        $data_insert['company'] = $ways->company;
        $data_insert['ways_source_desc'] = $ways_source_desc;
        $data_insert['other_no'] = $other_no;
        $insert_re = (new PayBaseController())->insert_day_order($data_insert);
        if (empty($insert_re)) {
            throw new BizException("订单写入失败");
        }
        return [
            "out_trade_no" => $out_trade_no,
            "embedPay" => $ways->company,
            "appId" => $this->appId,
            "path" => $path
        ];
    }

    protected function leshua(Store $store, StorePayWay $ways, array $payData): ResultVo
    {
        $configService = new LeshuaUnionPayConfigController();
        $mch = $configService->merchant($store->store_id, $store->pid);
        if (empty($mch)) {
            throw new BizException("商户号不存在");
        }
        $mchNo = $mch->mch_id;
        //配置取缓存
        $config = $configService->config($store->config_id);
        $logic = new LogicController();
        $resultVo = $logic->embedPayParams([
            "custId" => $mchNo,
            "orderNo" => $payData["out_trade_no"],
            "total_amount" => $payData["total_amount"],
            "store_id" => $payData["store_id"],
            "merchant_id" => $payData["merchant_id"],
            "notify_url" => $payData["notify_url"] ?? "",
            "company" => $ways->company,
        ], [
            "agetId" => $config->orgId,
            "key" => $config->key
        ]);
        if ($resultVo->getCode() != 1) {
            throw new BizException($resultVo->getMsg());
        }
        return $resultVo;
    }


    protected function getWaysPay(string $store_id, int $srore_id_pid): StorePayWay
    {
        $ways = StorePayWay::where('ways_source', "weixin")
            ->where('store_id', $store_id)
            ->where('status', 1)
            ->orderBy('sort', 'asc')
            ->first();
        if (empty($ways)) {
            $store_id = "";
            $srore_id_pid = Store::where('id', $srore_id_pid)
                ->select('store_id')
                ->first();
            if ($srore_id_pid) {
                $store_id = $srore_id_pid->store_id;
            }

            $ways = StorePayWay::where('ways_source', "weixin")
                ->where('store_id', $store_id)
                ->where('status', 1)
                ->orderBy('sort', 'asc')
                ->first();
        }

        return $ways;
    }


    public function getSignContent($params)
    {
        ksort($params);
        $stringToBeSigned = "";
        $i = 0;
        foreach ($params as $k => $v) {
            if (false === $this->checkEmpty($v) && "@" != substr((string)$v, 0, 1)) {
                // 转换成目标字符集
                // $v = $this->characet($v, $this->postCharset);
                if ($i == 0) {
                    $stringToBeSigned .= "$k" . "=" . "$v";
                } else {
                    $stringToBeSigned .= "&" . "$k" . "=" . "$v";
                }
                $i++;
            }
        }
        return $stringToBeSigned;
    }


    protected function checkEmpty($value)
    {
        if (!isset($value)) {
            return true;
        }
        if ($value === null) {
            return true;
        }
        if (is_string($value) && trim($value) === "") {
            return true;
        }
        return false;
    }

    public function getCostRate($ways_type, $user_id)
    {
        $user_rate_obj = UserRate::where('ways_type', $ways_type)
            ->where('user_id', $user_id)
            ->where('status', 1)
            ->orderby('created_at', 'desc')
            ->first();

        return $user_rate_obj;
    }

}